# This file is part of OrangeSpider. OrangeSpider is a meta model based
# development tool.
# 
# OrangeSpider is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# OrangeSpider is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with OrangeSpider.  If not, see <http://www.gnu.org/licenses/>.
#
# Copyright 2009 Stefan Nikolaus <OrangeSpiderMaster@googlemail.com>

from MetaModel import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import Ui
import Component
import Tree
import ComponentManager
import FastEdit
import Graph
import sys
import os
import shutil
import Builder
import Script
import Persistence

class NameDlg(QDialog):
    def __init__(self, parent = None):
        QDialog.__init__(self, parent)
        layout = QVBoxLayout(self)
        self.label = QLabel("Enter Name")
        layout.addWidget(self.label)
        self.editField = QLineEdit(self)
        layout.addWidget(self.editField)
        layout2 = QHBoxLayout()
        self.okButton = QPushButton("Ok")
        layout2.addWidget(self.okButton)
        self.cancelButton = QPushButton("Cancel")
        layout2.addWidget(self.cancelButton)
        layout.addLayout(layout2)
        self.connect(self.okButton, SIGNAL("clicked()"), 
                     self.accept)
        self.connect(self.cancelButton, SIGNAL("clicked()"), 
                     self.reject)

    def getName(self, text):
        self.label.setText(text)
        if self.exec_():
            return str(self.editField.text())
        return ""

class ProjectTreeView(Tree.RepositoryTreeView):
    def __init__(self, project, parent = None):
        self.project = project
        rootItem = project.getMainFolder()
        h1 = Tree.HeaderLevelDesc(None, "Folder")
        h2 = Tree.HeaderLevelDesc(h1, rootItem["Name"])
        h3 = Tree.DataLevelDesc(h2, Entity.CLASS, "OutgoingClasses", 
                                "Folder.Contains.Folder")
        h4 = Tree.DataLevelDesc(h2, Entity.CLASS, "OutgoingClasses", 
                                "Folder.Contains.File")
        h5 = Tree.DataLevelDesc(h2, Entity.CLASS, "OutgoingClasses", 
                                "Folder.Contains.Model")
        h6 = Tree.DataLevelDesc(h2, Entity.CLASS, "OutgoingClasses", 
                                "Folder.Contains.Script")
        h3.childLevels.append(h3)
        h3.childLevels.append(h4)
        h3.childLevels.append(h5)
        h3.childLevels.append(h6)
        Tree.RepositoryTreeView.__init__(self, rootItem, h1, parent)
        self.openActionGraph = QAction("&Open with Graph", self)
        self.openActionFastEdit = QAction("&Open with FastEdit", self)
        self.openActionMatrixBrowser = QAction("&Open with MatrixBrowser", self)
        self.createFolderAction = QAction("&Create Folder", self)
        self.createMMMAction = QAction("Create &MMM", self)
        self.createDIAGRAMAction = QAction("Create &DIAGRAM", self)
        self.instantiiateAction = QAction("Instantiiate", self)
        self.createScriptAction = QAction("Create script", self)
        self.executeScriptAction = QAction("Execute script", self)
        self.saveAction = QAction("Save", self)
        self.deleteAction = QAction("Delete", self)
        self.importAction = QAction("Import", self)
        self.signalMapper = None
        self.signalMapper = QSignalMapper()
        self.connect(self.createFolderAction, SIGNAL("triggered(bool)"), 
                     self.createFolder)
        self.connect(self.createMMMAction, SIGNAL("triggered(bool)"), 
                     self.signalMapper, SLOT("map()"))
        self.signalMapper.setMapping(self.createMMMAction, 
                                     "SpiderMMM")
        self.connect(self.createDIAGRAMAction, SIGNAL("triggered(bool)"), 
                     self.signalMapper, SLOT("map()"))
        self.signalMapper.setMapping(self.createDIAGRAMAction, 
                                     "SpiderDIAGRAM")
        self.connect(self.signalMapper, SIGNAL("mapped(const QString &)"),
                     self.createActionSlot)

        self.createSQLAction = QAction("Create &SQL", self)
        self.connect(self.createSQLAction, SIGNAL("triggered(bool)"),
                     self.signalMapper, SLOT("map()"))
        self.signalMapper.setMapping(self.createSQLAction, 
                                     "SpiderSQL")

        self.createINIAction = QAction("Create &INI", self)
        self.connect(self.createINIAction, SIGNAL("triggered(bool)"), 
                     self.signalMapper, SLOT("map()"))
        self.signalMapper.setMapping(self.createINIAction, 
                                     "SpiderINI")

        self.connect(self.openActionGraph, SIGNAL("triggered(bool)"), 
                     self.openGraph)
        self.connect(self.openActionFastEdit, SIGNAL("triggered(bool)"), 
                     self.openFastEdit)
        self.connect(self.openActionMatrixBrowser, SIGNAL("triggered(bool)"), 
                     self.openMatrixBrowser)
        self.connect(self.instantiiateAction, SIGNAL("triggered(bool)"), 
                     self.instantiiate)
        self.connect(self.saveAction, SIGNAL("triggered(bool)"), 
                     self.saveModel)
        self.connect(self.deleteAction, SIGNAL("triggered(bool)"), 
                     self.deleteItem)
        self.connect(self.importAction, SIGNAL("triggered(bool)"), 
                     self.importFile)
        self.connect(self.createScriptAction, SIGNAL("triggered(bool)"), 
                     self.createScriptSlot)
        self.connect(self.executeScriptAction, SIGNAL("triggered(bool)"), 
                     self.executeScriptSlot)

        self.createActions = []
        
    def contextMenuEvent(self, e):
        item = self._getCurrentItem()
        if item:
            if item.intention["Name"] == "Folder":
                for action in self.createActions:
                    del action
                menu = QMenu(self)
                menu.addAction(self.createFolderAction)
                menu.addAction(self.createMMMAction)
                menu.addAction(self.createDIAGRAMAction)
                menu.addAction(self.createScriptAction)
                menu.addSeparator()
                menu.addAction(self.createSQLAction)
                menu.addAction(self.createINIAction)

                metaMetaModels = self.project.getMetaMetaModels()
                for metaMetaModel in metaMetaModels:
                    action = QAction("Create " + metaMetaModel, self)
                    self.createActions.append(action)
                    self.connect(action, SIGNAL("triggered(bool)"), 
                                 self.signalMapper, SLOT("map()"))
                    self.signalMapper.setMapping(action, metaMetaModel)
                    menu.addAction(action)
                menu.addSeparator()
                menu.addAction(self.deleteAction)
                menu.addAction(self.importAction)
                menu.popup(self.mapToGlobal(e.pos()))

            elif item.intention["Name"] == "Model":
                menu = QMenu(self)
                menu.addAction(self.openActionGraph)
                menu.addAction(self.openActionFastEdit)
                menu.addAction(self.openActionMatrixBrowser)
                menu.addAction(self.saveAction)
                if item["Type"] == "SpiderMMM":
                    menu.addAction(self.instantiiateAction)
                menu.addAction(self.deleteAction)
                menu.popup(self.mapToGlobal(e.pos()))

            elif item.intention["Name"] == "Script":
                menu = QMenu(self)
                menu.addAction(self.executeScriptAction)
                menu.addAction(self.deleteAction)
                menu.popup(self.mapToGlobal(e.pos()))

            elif item.intention["Name"] == "File":
                menu = QMenu(self)
                menu.addAction(self.deleteAction)
                menu.popup(self.mapToGlobal(e.pos()))
                
    def createActionSlot(self, metaModelType):
        print "createActionSlot", metaModelType
        item = self._getCurrentItem()
        if item:
            newName = self._getName()
            if newName != "":
                self.project.createMetaModel(item, str(newName), str(metaModelType))
                self.project.save()
                self.resetView()

    def createScriptSlot(self):
        item = self._getCurrentItem()
        if item:
            newName = self._getName()
            f = self.project.createScript(item, newName)
            self.project.save()
            self.resetView()

    def executeScriptSlot(self):
        item = self._getCurrentItem()
        if item:
            self.project.executeScript(item)
            
    def createFolder(self):
        item = self._getCurrentItem()
        if item:
            newName = self._getName()
            f = self.project.createFolder(item, newName)
            self.project.save()
            self.resetView()

    def instantiiate(self):
        item = self._getCurrentItem()
        if item:
            r = self.project.loadModel(item)
            if r:
                if r["Type"] == "SpiderMMM":
                    newName = self._getName()
                    if newName != "":
                        self.project.instantiiate(item, r, newName)
                        self.resetView()


    def saveModel(self):
        item = self._getCurrentItem()
        if item:
            self.project.saveModel(item)

    def openGraph(self):
        item = self._getCurrentItem()
        if item:
            r = self.project.loadModel(item)
            if r:
                import Kernel

                graph = Kernel.componentManager.createComponent("Spider.Graph.Graph")
                iProject = graph.interface("Spider.IProject")
                assert(iProject)
                iProject.open(self, r, item)

    def openFastEdit(self):
        item = self._getCurrentItem()
        if item:
            r = self.project.loadModel(item)
            if r:
                import Kernel
                fe = Kernel.componentManager.createComponent("Spider.FastEdit.FastEdit")
                iProject = fe.interface("Spider.IProject")
                assert(iProject)
                iProject.open(self, r, item)
  
    def openMatrixBrowser(self):
        print "openMatrixBrowser"
        item = self._getCurrentItem()
        if item:
            if item.intention["Name"] == "Model":
                r = self.project.loadModel(item)
                if r:
                    import Kernel
                    mb = Kernel.componentManager.createComponent("Spider.Ui.MatrixBrowser")
                    iProject = mb.interface("Spider.IProject")
                    assert(iProject)
                    iProject.open(self, r, item)

    def deleteItem(self):
        item = self._getCurrentItem()
        if item:
            if item.intention["Name"] == "Folder":
                if item["Type"] != "Folder":
                    # NO deletion of standard folders
                    return
            self.project.deleteItem(item)
            self.project.save()
            self.resetView()

    def importFile(self):
        filenames = QFileDialog.getOpenFileNames(self, "Select file", ".",
               "Files (*.*)")
        ok = False
        for filename in filenames:
            filename = str(filename)
            if filename:
                item = self._getCurrentItem()
                if item:
                    r = self.project.importFile(item, filename)
                    if r:
                        ok = True
        if ok:
            self.project.save()
            self.resetView()

    def _getCurrentItem(self):
        sm = self.selectionModel()
        ci = sm.currentIndex()
        m = self.treeModel
        item = m.data(ci, Tree.TreeItem.KeyDataRole)
        return item
    def _getName(self):
        nd = NameDlg(self)
        if nd.exec_():
            return str(nd.editField.text())
        return ""

class ProjectDlg(QDialog):
    def __init__(self, project, parent=None):
        QDialog.__init__(self, parent)
        #QLabel("Test", self)
        self.project = project
        layout = QGridLayout(self)
        self.setWindowTitle("Spider Project")
        menuBar = QMenuBar(self)
        layout.addWidget(menuBar, 0, 0)
        menu = menuBar.addMenu("Data")
        self.projectDataAction = QAction("Project data", self)
        menu.addAction(self.projectDataAction)
        self.connect(self.projectDataAction, SIGNAL("triggered()"), self._showProjectData)

        self.projectSaveAction = QAction("Save project", self)
        menu.addAction(self.projectSaveAction)
        self.connect(self.projectSaveAction, SIGNAL("triggered()"), self._save)

        self.projectUpgradeToPackage = QAction("Upgrade to package", self)
        menu.addAction(self.projectUpgradeToPackage)
        self.connect(self.projectUpgradeToPackage, SIGNAL("triggered()"), self._upgradeToPackage)

        self.treeView = ProjectTreeView(project)
        #self.model = Tree.TreeModel()
        #self.model.rootItem = Tree.TreeItem(None, project.getMainFolder(), h1)
        #t.setModel(self.model)
        layout.addWidget(self.treeView, 1, 0)
        self.setLayout(layout)

        shortcut = QShortcut(QKeySequence.Refresh, self)
        self.connect(shortcut, SIGNAL("activated()"), self._refresh)
        self.resize(250, 400)
        self.setWindowIcon(QIcon("img/spiderIco.png"))

    def _refresh(self):
        self.treeView.resetView()

    def _upgradeToPackage(self):
        self.project.upgradeToPackage()
        
    def _showProjectData(self):
        r = self.project.repository
        mb = Ui.MatrixWidget(r)
        mb.exec_()
        #fe = FastEdit.FastEditDlg(r)
        #fe.exec_()

    def _save(self):
        self.project.save()
    
"""
listdir( path) 
mkdir( path[, mode]) 
rename( src, dst) 
removedirs( path) 
remove( path)  file
rmdir( path) 
"""
class Project:
    def __init__(self):
        self.baseFolder = ""
        self.repository = None

    def create(self, folder, name):
        self.repository = buildMetaModel("Project", "SpiderPROJECT", Watcher())
        self.baseFolder = folder

        mainFolder = self.createFolder(None, name, "Project")
        newFolder = folder + os.sep + name
        self.repository["FileName"] = newFolder + os.sep + name + ".spid"

        # create default folders
        configFolder = self.createFolder(mainFolder, 
                         "Config", "Configuration")
        metaModels = self.createFolder(configFolder, 
                         "MetaModels", "Configuration")
        diagrams = self.createFolder(configFolder, 
                          "DiagramDefinitions", "Configuration")
        components = self.createFolder(configFolder, 
                          "Components", "Configuration")

        self.save()
        return mainFolder
    def getMainFolder(self):
        return self.repository.find("Folder", "Type", "Project")
    def createFolder(self, currentFolder, name, type="Folder"):
        folder = self.repository.Class("Folder")
        name = self.createUniqueName(currentFolder, name)
        folder["Name"] = name
        folder["Type"] = type
        if currentFolder:
            self.repository.Assoc(currentFolder, folder, "Contains")
        path = self._getPath(folder)
        os.mkdir(path)
        return folder
    def deleteFolder(self, folder):
        folderList = []

        # first collect all files and folder to delete
        self._createDeleteList(folder, folderList)

        # then first delete the files   
        for projectItem in folderList:
            if projectItem.intention["Name"] == "Model":
               self.deleteMetaModel(projectItem)
            elif projectItem.intention["Name"] == "File":
               self.deleteFile(projectItem)
            elif projectItem.intention["Name"] == "Script":
               self.deleteFile(projectItem)

        # second delete the folders, so we delete from last to first
        for projectItem in folderList:
            if projectItem.intention["Name"] == "Folder":
               path = self._getPath(projectItem)
               os.rmdir(path)

        for projectItem in folderList:
            if projectItem.intention["Name"] == "Folder":
                self.repository.deleteClass(projectItem)

    def _createDeleteList(self, folder, folderList):
        for childFile in folder.eachOutgoingClass("Folder.Contains.File"):
            folderList.append(childFile)
        for childFile in folder.eachOutgoingClass("Folder.Contains.Script"):
            folderList.append(childFile)
        for childFile in folder.eachOutgoingClass("Folder.Contains.Model"):
            folderList.append(childFile)
        for childFolder in folder.eachOutgoingClass("Folder.Contains.Folder"):
            self._createDeleteList(childFolder, folderList)
        folderList.append(folder)
        
    def createMetaModel(self, currentFolder, name, typ):
        import Kernel
        if Kernel.componentManager.isBuiltIn(typ):
            file = self.repository.Class("Model")
            assert(currentFolder)
            if currentFolder:
                self.repository.Assoc(currentFolder, file, "Contains")
            newName = self.createUniqueName(currentFolder, name + ".spid")
            file["Name"] = newName
            file["Type"] = typ
            path = self._getPath(file)
            r = Kernel.componentManager.createMetaModel(name, typ, path)
            file["UUID"] = r["UUID"]
            self.saveRep(r)
            return r
        else:
            metaMetaModel = Kernel.componentManager.getMetaMetaModel(typ)
            assert(metaMetaModel)
            return self._instantiiate(currentFolder, metaMetaModel, name)

    def deleteMetaModel(self, metamodelfile):
        import Kernel
        Kernel.componentManager.removeMetaModel(metamodelfile["UUID"])
        self.deleteFile(metamodelfile)
    def deleteFile(self, file):
        path = self._getPath(file)
        self.repository.deleteClass(file)
        try:
           os.remove(path)
        except OSError, e:
           if e.errno != 2:
               raise
        self.save()
    def deleteItem(self, item):
        if item.intention["Name"] == "Folder":
            self.deleteFolder(item)
        elif item.intention["Name"] == "Model":
            self.deleteMetaModel(item)
        else:
            self.deleteFile(item)

    def load(self, filename, execute=True):
        im = Persistence.Importer()
        self.repository = im.load(filename)
        self.repository.watcher.addListener(Ui.Emitter(), "Emitter")

        self.baseFolder = os.path.dirname(filename)
        self.baseFolder = os.path.dirname(self.baseFolder)
        self.repository["FileName"] = filename
        if execute:
            self._autoLoad()
        return self.getMainFolder()

    def deleteProject(self, filename):
        print "Delete:" + filename
        mainFolder = self.load(filename)
        if mainFolder:
            # first remove project
            os.remove(filename)
            # then delete the whole project
            self.deleteItem(mainFolder)            

    def loadModelByName(self, currentFolder, path):
        item = self.getItemByPath(currentFolder, path)
        if item:
            if item.intention["Name"] == "Model":
                return self.loadModel(item)
            else:
                print "project::loadModelByName - found item is not a model"
        else:
            print "project::loadModelByName - item not found"

    def getItemPath(self, currentFolder, path):
        item = self.getItemByPath(currentFolder, path)
        if item:
            return self._getPath(item)
        else:
            return ""
        
    def getItemByPath(self, currentFolder, path):
        assert(currentFolder.intention["Name"] == "Folder")
        result = currentFolder
        paths = path.split("/")
        for path in paths:
            if path == ".":
                # same level
                pass
            elif path == "..":
                # one level up
                parentAssoc = "Folder.Contains." + result.intention["Name"]
                parent = result.firstIncomingClass(parentAssoc)
                if parent:
                    result = parent
                else:
                    print "project::getItemByPath - Parent folder not found"
                    return None
            else:
                # down one level
                if result.intention["Name"] == "Folder":
                    result = self._getSubItem(result, path)
                else:
                    # Parent item is not a folder
                    print "project::getItemByPath - Parent item is not a folder"
                    return None
                
        return result
            
    def loadModel(self, item):
        import Kernel
        if item.intention["Name"] == "Model":
            path = self._getPath(item)
            r = Kernel.componentManager.openMetaModel(path, item["UUID"])
            return r
        return None            
        
    def save(self):
        self.saveRep(self.repository)

    def getMetaMetaModels(self):
        import Kernel
        metaModelNames = [r["Name"] for r in Kernel.componentManager.getMetaMetaModels()]
        return metaModelNames

    def instantiiate(self, item, r, newName):
        currentFolder = item.firstIncomingClass("Folder.Contains.Model")
        self._instantiiate(currentFolder, r, newName)        

    def createScript(self, currentFolder, newName):
        script = self.repository.Class("Script")
        newName = self.createUniqueName(currentFolder, newName + ".py")
        script["Name"] = newName
        if currentFolder:
            self.repository.Assoc(currentFolder, script, "Contains")
            path = self._getPath(script)
            f = open(path, "w")
            f.write("import Kernel\n")
            f.write("\n")
            f.write("# Spider script\n")
            f.write("env = globals()\n")
            f.close()

    def executeScript(self, item):
        import Kernel
        path = self._getPath(item)
        se = Script.ScriptEnvironment(
            {"Project":self,
             "ProjectItem": item,
             "CurrentFolder": item.firstIncomingClass("Folder.Contains.Script"),
             "Path": path,
             "NameDlg": NameDlg()
             })
        s = Script.Script(path, se)
        s.execute()

    def _instantiiate(self, currentFolder, r, newName):
        import Kernel
        assert(currentFolder)
        file = self.repository.Class("Model")
        metaModel = getFirst(r.metaClasses["MetaModel"].extension)
        if not metaModel:
            s = "No meta model instance found in MetaModel "
            s += r["Name"]
            QMessageBox.critical(None, "Spider", s)
            return 

        if currentFolder:
            self.repository.Assoc(currentFolder, file, "Contains")
        newName = newName + ".spid"
        newName = self.createUniqueName(currentFolder, newName)
        file["Name"] = newName
        file["Type"] = metaModel["Type"]
        path = self._getPath(file)

        mmc = Component.MetaModelConverter()
        rInstance = mmc.instantiiate(r)
        rInstance.watcher = Watcher()

        Kernel.componentManager.addMetaModel(path, rInstance)
        file["UUID"] = rInstance["UUID"]
        self.save()
        self.saveRep(rInstance)
        return rInstance

    def saveModel(self, item):
        r = self.loadModel(item)
        if r:
            self.saveRep(r)

    def importFile(self, currentFolder, filename):
        extension = os.path.splitext(filename)[1]
        if extension == ".spid":
            return self.importModel(currentFolder, filename)
        else:
            assert(currentFolder)
            if extension == ".py":
                ob = self.repository.Class("Script")
            else:
                ob = self.repository.Class("File")
            self.repository.Assoc(currentFolder, ob, "Contains")
            newName = os.path.basename(filename)
            newName = self.createUniqueName(currentFolder, newName)
            ob["Name"] = newName
            path = self._getPath(ob)
            print "Copying file " + path
            shutil.copy(filename, path)
            return ob
    
    def importModel(self, currentFolder, filename):
        import Kernel
        im = Persistence.Importer()
        r = im.load(filename)
        if r:
            newName = os.path.splitext(os.path.basename(filename))[0]
            assert(currentFolder)
            file = self.repository.Class("Model")
            self.repository.Assoc(currentFolder, file, "Contains")
            newName = newName + ".spid"
            newName = self.createUniqueName(currentFolder, newName)
            file["Name"] = newName
            file["Type"] = r["Type"]
            path = self._getPath(file)

            # create a new uuid
            print "Importing model " + path
            r["UUID"] = r.uuid()
            file["UUID"] = r["UUID"]
            Kernel.componentManager.addMetaModel(path, r)
            self.save()
            self.saveRep(r)
            return file
        return None

    def loadDiagramDef(self, mmType):
        main = self.getMainFolder()
        assert(main)
        config = main.findOutgoingClass("Folder.Contains.Folder", 
                                        "Name", "Config")
        assert(config)
        definitions = config.findOutgoingClass("Folder.Contains.Folder", 
                                              "Name", "DiagramDefinitions")
        assert(definitions)
        diagramDef = definitions.findOutgoingClass("Folder.Contains.Model", 
                                                   "Name", mmType + ".spid")
        diagramDefRep = self.loadModel(diagramDef)
        assert(diagramDefRep)
        return diagramDefRep        

    def upgradeToPackage(self):
        # Inserts the package node and connects it to the project root folder
        main = self.getMainFolder()
        package = main.firstIncomingClass("Package.Has.Folder")
        if not package:
            r = self.repository
            package = r.Class("Package")
            r.Assoc(package, main, "Has")
        
    def _autoLoad(self):
        self._loadDefaultMetaModels()
        self._loadDefaultScripts()

    def _loadDefaultMetaModels(self):
        try:
            main = self.getMainFolder()
            config = main.findOutgoingClass("Folder.Contains.Folder", 
                                            "Name", "Config")
            assert(config)
            # First we read all meta models from the config folder
            metaModels = config.findOutgoingClass("Folder.Contains.Folder", 
                                                  "Name", "MetaModels")
            assert(metaModels)
            for metaModel in metaModels.eachOutgoingClass("Folder.Contains.Model"):
                if metaModel["Type"] == "SpiderMMM":
                    self.loadModel(metaModel)
        except:
            s = "Error loading default meta model"
            QMessageBox.critical(None, "Spider", s)


    def _loadDefaultScripts(self):
        main = self.getMainFolder()
        config = main.findOutgoingClass("Folder.Contains.Folder", 
                                        "Name", "Config")
        assert(config)

        # Then we execute all scripts in the components folder
        # This means that we register all new components for usage of other 
        components = config.findOutgoingClass("Folder.Contains.Folder", 
                                              "Name", "Components")
        assert(components)
        for script in components.eachOutgoingClass("Folder.Contains.Script"):
            self.executeScript(script)

    def createUniqueName(self, currentFolder, name):
        if self.isUnique(currentFolder, name):
            return name
        else:
            counter = 0
            baseName = name + str(counter)
            while not self.isUnique(currentFolder, baseName):
                counter += 1
                baseName = name + str(counter)
            return baseName

    def _getSubItem(self, currentFolder, testName):
        c = currentFolder.findOutgoingClass("Folder.Contains.Folder",
                "Name", testName)
        if c:
            return c
        c = currentFolder.findOutgoingClass("Folder.Contains.Model",
                "Name", testName)
        if c:
            return c
        c = currentFolder.findOutgoingClass("Folder.Contains.File",
                "Name", testName)
        if c:
            return c
        c = currentFolder.findOutgoingClass("Folder.Contains.Script",
                "Name", testName)
        if c:
            return c
        return None

    def isUnique(self, currentFolder, testName):
        if not currentFolder:
            return 1
        c = self._getSubItem(currentFolder, testName)
        if c:
            return 0
        return 1        

    def saveRep(self, r):
        exporter = Persistence.Exporter(r)
        exporter.save(r["FileName"])
    def getPath(self, fileObject):
        return self._getPath(fileObject)
    def _getPath(self, fileObject):
        parentAssoc = "Folder.Contains." + fileObject.intention["Name"]
        parent = fileObject.firstIncomingClass(parentAssoc)
        if parent:
            result = self._getPath(parent) + os.sep
        else:
            result = self.baseFolder + os.sep
        result += fileObject["Name"]
        return result

class ProjectComponent(Component.Component):
    def __init__(self):
        Component.Component.__init__(self)
        self.project = Project()

    def interface(self, interfaceName):
        if interfaceName == "Spider.IManagedComponent":
            return self

    # Interface Spider.IManagedComponent
    @staticmethod
    def setupComponentType(rSpiderCOMP):
        return Component.Component._setupComponentType(rSpiderCOMP , "Spider.Project.Project",
                                                       "Project management",
                                                       1, ["Spider.IManagedComponent"])

    def show(self):
        self.pd = ProjectDlg(self.project)
        self.pd.show()

    def create(self, folder, name):
        return self.project.create(folder, name)

    def deleteProject(self, filename):
        return self.project.deleteProject(filename)
    def load(self, filename, execute=True):
        return self.project.load(filename, execute)
    def save(self):
        self.project.save()


if __name__ == "__main__":
    sys.path.append("./Packages")
    print sys.path

    app = QApplication(sys.argv)
    action = "open"
    file = ""
    name = ""
    if len(sys.argv) >= 2:
        action = sys.argv[1]
    if len(sys.argv) >= 3:
        file = sys.argv[2]
    if len(sys.argv) >= 4:
        name = sys.argv[3]

    projectComp = ProjectComponent()
    if action == "create":
        if file == "":
            file = "D:/Users/sn/Development/Repository/Data/TestSpider"
        if name == "":
            name = "Test1"
        f1 = projectComp.create(file, name)
        projectComp.show()
    elif action == "delete":
        if file == "":
            file = "D:/Users/sn/Development/Repository/Data/TestSpider/Test1/Test1.spid"
        projectComp.deleteProject(file)        
    else:
        if file == "":
            file = "D:/Users/sn/Development/Repository/Data/TestSpider/Test1/Test1.spid"
        projectComp.load(file)
        projectComp.show()

    sys.exit(0)


#        pOld = package.repository.find("Package", "Name", "org.Spider.Test1")
#        fOld = package.repository.find("Folder", "Name", "Test1")
#        package.repository.Assoc(pOld, fOld, "Has")
#        package.save()
